package com.gztms.blogmgnt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gztms.blogmgnt.mapper.BlogMapper;
import com.gztms.blogmgnt.pojo.Blog;
import com.gztms.blogmgnt.pojo.BlogReview;
import com.gztms.blogmgnt.pojo.BlogStatus;
import com.gztms.blogmgnt.pojo.BlogType;
import com.gztms.blogmgnt.pojo.vo.BlogDetailVO;
import com.gztms.blogmgnt.pojo.vo.BlogVO;
import com.gztms.blogmgnt.pojo.vo.PageVO;
import com.gztms.blogmgnt.service.BlogReviewService;
import com.gztms.blogmgnt.service.BlogService;
import com.gztms.blogmgnt.service.BlogTypeService;
import com.gztms.enums.AppCodeEnum;
import com.gztms.enums.RedisKey;
import com.gztms.travelmgnt.pojo.Attractions;
import com.gztms.usermgnt.mapper.UserMapper;
import com.gztms.usermgnt.pojo.User;
import com.gztms.usermgnt.service.UserService;
import com.gztms.utils.BeanCopyUtils;
import com.gztms.utils.RedisCache;
import com.gztms.utils.ResultUtil;
import com.gztms.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Zoey
 * @date 2023/4/23 0:23
 * @Description TODO
 **/
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper,Blog> implements BlogService {

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private BlogTypeService blogTypeService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private BlogReviewService blogReviewService;





    @Override
    public ResultUtil addBlog(Blog blog) {
        save(blog);
        return ResultUtil.okResult();
    }


    @Override
    public ResultUtil delBlog(Integer id) {
        int res = blogMapper.deleteById(id);
        if (res == 1) {
            return new ResultUtil(ResultUtil.SUCCESS,"文章删除成功");
        }else {
            return new ResultUtil(ResultUtil.SERVER_ERROR,"文章删除失败");
        }
    }

    @Override
    public ResultUtil updateBlog(Blog blog) {
        // 判断文章是否为为审核不通过
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(Blog::getStatus,BlogStatus.BLOG_STATUS_FAILED);

        // 每次修改文章后，将其改为待审核状态
        blog.setStatus(BlogStatus.BLOG_STATUS_UNCHECKED);
        boolean isUpdate = updateById(blog);

        if (isUpdate) {
            // 将blog的状态重新设置为待审核
//            blog.setStatus(BlogStatus.BLOG_STATUS_UNCHECKED);
//            updateById(blog);
            return new ResultUtil(ResultUtil.SUCCESS, "操作成功");
        }
        return ResultUtil.errorResult(AppCodeEnum.SYSTEM_ERROR);
//        int res = blogMapper.updateById(blog);
//        if (res == 1) {
//            return new ResultUtil(ResultUtil.SUCCESS,"文章修改成功");
//        }else {
//            return new ResultUtil(ResultUtil.SERVER_ERROR,"文章修改失败");
//        }
    }

    @Override
    public ResultUtil getAllBlogs(int pageNum, int pageSize) {
        Page<Blog> blogsPage = new Page(pageNum,pageSize);
        Page<Blog> blogs = blogMapper.getAllBlogs(blogsPage);
        List<Blog> records = blogs.getRecords();

        Map<String, Object> map = new HashMap<>();
        map.put("currentPage", blogs.getCurrent());
        map.put("total",blogs.getTotal());
        map.put("blogs",blogs.getRecords());
        return new ResultUtil(ResultUtil.SUCCESS,"文章查询成功", map);

    }

    @Override
    public ResultUtil getAllTypes() {
        List<BlogType> blogTypes = blogMapper.getAllBlogTypes();
        Map<String, Object> map = new HashMap<>();
        map.put("blogTypes", blogTypes);
        return new ResultUtil(ResultUtil.SUCCESS,"文章类型查询成功", map);

    }

    @Override
//    @Cacheable(value = "getHotBlogs", key = "targetClass + methodName")
    public ResultUtil getHotBlogs() {
        // 查询热门文章
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        // 状态已审核过的正式文章，并且按照浏览量进行降序排序，前10条
        wrapper.eq(Blog::getStatus, BlogStatus.BLOG_STATUS_SUCCESS);
        wrapper.orderByDesc(Blog::getViewCount);

        List<BlogVO> cacheList = redisCache.getCacheList(RedisKey.HOT_BLOGS);
        if (cacheList.size() == 0) {
            Page<Blog> page = new Page<>(1,8);
            blogMapper.selectPage(page, wrapper);
            List<Blog> blogs = page.getRecords();
            // bean拷贝
            List<BlogVO> blogVOList = new ArrayList<>();
            for (Blog blog : blogs) {
                BlogVO vo = new BlogVO();
                BeanUtils.copyProperties(blog,vo);
                // 修改成redis的值
                Integer viewCount = redisCache.getCacheMapValue("blog:viewCount", vo.getBid().toString());
                vo.setViewCount(viewCount);
                // 获取用户名
                User user = userService.getById(blog.getCreatedBy());
                vo.setUsername(user.getUsername());
                blogVOList.add(vo);
            }
            redisCache.setCacheList(RedisKey.HOT_BLOGS, blogVOList);
            long time = (30 * 60);
            redisCache.expire(RedisKey.HOT_BLOGS, time);
            Map<String, Object> map = new HashMap<>();
            map.put("hotBlogs", blogVOList);
            return new ResultUtil(ResultUtil.SUCCESS,"文章查询成功", map);
        } else {
            // 重新获取viewCount的数值
            for (BlogVO blogVO : cacheList) {
                Integer viewCount = redisCache.getCacheMapValue("blog:viewCount", blogVO.getBid().toString());
                blogVO.setViewCount(viewCount);
            }
            Map<String, Object> map = new HashMap<>();
            map.put("hotBlogs", cacheList);
            return new ResultUtil(ResultUtil.SUCCESS,"文章查询成功", map);
        }



    }

    @Override
    public ResultUtil getBlogList(Integer pageNum, Integer pageSize, Integer type, String title, Integer isUp) {
        LambdaQueryWrapper<Blog> blogWrapper = new LambdaQueryWrapper<>();
        // 根据条件参数进行查询
        boolean flag = false;
        try{
            flag = SecurityUtils.isAdmin();
        }catch (ClassCastException e){
            
        }

        if (!flag) {
            blogWrapper.eq(Blog::getStatus, BlogStatus.BLOG_STATUS_SUCCESS);
        }
//        blogWrapper.eq(Blog::getStatus, BlogStatus.BLOG_STATUS_SUCCESS);
        // 类型
        if (!Objects.isNull(type)&&type>0) {
            blogWrapper.eq(Blog::getType, type);
        }
        // 标题
        if (Objects.nonNull(title) && !StringUtils.isEmpty(title)) {
            blogWrapper.like(Blog::getTitle, title);
        }
        // 时间顺序
        if (BlogStatus.BLOG_DESC_BY_TIME.equals(isUp+"")) {
            blogWrapper.orderByDesc(Blog::getCreateTime);
        }

        blogWrapper.orderByAsc(Blog::getCreateTime);
        // todo 从redis查询数据
//        Object cacheObject = redisCache.getCacheObject(RedisKey.HOT_BLOGS);
//        if (Objects.isNull(cacheObject)) {
//
//        }

        Page<Blog> page = new Page<>(pageNum,pageSize);
        page(page,blogWrapper);
        List<Blog> records = page.getRecords();

        // 查询分类名称和用户名称
        if (records.size()>0) {
            records.stream()
                    .map( blog -> blog.setTypeName(blogTypeService.getById(blog.getType()).getTypeName()))
                    .map( blog -> blog.setUsername(userService.getById(blog.getCreatedBy()).getUsername()))
                    .collect(Collectors.toList());
        }

        // 封装查询数据
        List<BlogVO> blogVOList = BeanCopyUtils.copyBeanList(records, BlogVO.class);
        blogVOList.stream()
                .map(blogVO -> {
                    LambdaQueryWrapper<BlogReview> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(BlogReview::getBlogId, blogVO.getBid());
                    queryWrapper.orderByDesc(BlogReview::getCreateTime);
                    List<BlogReview> blogReviews = blogReviewService.getBaseMapper().selectList(queryWrapper);
                    if (blogReviews.size()>0) {
                        blogVO.setReviewStatus(blogReviews.get(0).getStatus());
                    }
                    blogVO.setAvatar(userService.getById(blogVO.getCreatedBy()).getAvatar());
                    // 修改成redis的值
                    Integer viewCount = redisCache.getCacheMapValue("blog:viewCount", blogVO.getBid().toString());
                    blogVO.setViewCount(viewCount);
                    return blogVO;
                })
                .collect(Collectors.toList());

        Map<String, Object> map = new HashMap<>();
        map.put("blogList",blogVOList);
        map.put("total",page.getTotal());
        return new ResultUtil(ResultUtil.SUCCESS, "查询成功", map);
    }

    @Override
    public ResultUtil getBlogDetail(Integer id) {
        Blog blog = getById(id);
        // 判断是否为管理员
        try {
            if (!SecurityUtils.isAdmin()) {
                // 更新viewCount
                updateViewCount(id);
            }
        }catch (Exception e) {
            System.out.println(e);
        }


        // 从redis中查询viewCount
        Integer viewCount = redisCache.getCacheMapValue("blog:viewCount", id.toString());
        blog.setViewCount(viewCount);
        // 转换VO类
        BlogDetailVO blogDetailVO = BeanCopyUtils.copyBean(blog, BlogDetailVO.class);
        Integer typeId = blogDetailVO.getType();
        BlogType blogType = blogTypeService.getById(typeId);
        if (blogType!=null) {
            blogDetailVO.setTypeName(blogType.getTypeName());
        }
        User user = userService.getById(blogDetailVO.getCreatedBy());
        blogDetailVO.setUsername(user.getUsername());
        blogDetailVO.setAvatar(user.getAvatar());
        // 封装数据并返回
        Map<String, Object> map = new HashMap<>();
        map.put("blog",blogDetailVO);
        return new ResultUtil(ResultUtil.SUCCESS, "查询成功", map);
    }

    @Override
    public ResultUtil updateViewCount(Integer id) {
        // 1、更新redis中的数据
        redisCache.incrementCacheMapValue("blog:viewCount",id.toString(),1);
        return ResultUtil.okResult();
    }

    @Override
    public ResultUtil uploadImage(String imgUrl) {
        if (StringUtils.isEmpty(imgUrl)) {
            return new ResultUtil(ResultUtil.SERVER_ERROR,"图片上传失败");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("imgUrl", imgUrl);
        return new ResultUtil(ResultUtil.SUCCESS,"图片上传成功",map);
    }

    @Override
    public ResultUtil getBlogByUid(Integer pageNum, Integer pageSize, Integer status, String uid) {
        Page<Blog> blogPage = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Blog::getCreatedBy, uid);
        if (Objects.nonNull(status) && status != 3) {
            queryWrapper.eq(Blog::getStatus, status);
        }

        Page<Blog> page = page(blogPage,queryWrapper);
        List<Blog> blogs = page.getRecords();
        List<BlogVO> blogVOS = blogs.stream()
                .map(blog -> toBlogVO(blog))
                .collect(Collectors.toList());


        Map<String, Object> map = new HashMap<>();
        map.put("blogList",blogVOS);
        map.put("total",page.getTotal());
        return new ResultUtil(ResultUtil.SUCCESS, "查询成功", map);
    }

    private BlogVO toBlogVO(Blog blog){
        BlogVO blogVO = BeanCopyUtils.copyBean(blog, BlogVO.class);
        User user = userService.getById(blogVO.getCreatedBy());
        blogVO.setUsername(user.getUsername());
        blogVO.setAvatar(user.getAvatar());
        String typeName = blogTypeService.getById(blogVO.getType()).getTypeName();
        blogVO.setTypeName(typeName);
        return blogVO;
    }


}
